package cn.edu.xmu.oomall.customer.dao.bo;


import cn.edu.xmu.javaee.core.exception.BusinessException;
import cn.edu.xmu.javaee.core.model.ReturnNo;
import cn.edu.xmu.javaee.core.model.dto.UserDto;
import cn.edu.xmu.oomall.customer.dao.CouponDao;
import cn.edu.xmu.oomall.customer.dao.openfegin.CouponActDao;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.ToString;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import java.time.LocalDateTime;

/**
 * 优惠活动
 */
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@ToString(callSuper = true, doNotUseGetters = true)
public class CouponAct extends Activity {

    private RedissonClient redissonClient;

    public static final String ACTCLASS = "couponActDao";

    private LocalDateTime couponTime;

    private Integer quantity;

    private Integer quantityType;

    private Integer validTerm;

    private CouponDao couponDao;

    private CouponActDao couponActDao;

    public CouponAct() {
        super();
        this.actClass = ACTCLASS;
    }


    public CouponActDao getCouponActDao() {
        return couponActDao;
    }

    public void setCouponActDao(CouponActDao couponActDao) {
        this.couponActDao = couponActDao;
    }

    public CouponDao getCouponDao() {
        return couponDao;
    }

    public void setCouponDao(CouponDao couponDao) {
        this.couponDao = couponDao;
    }

    public RedissonClient getRedissonClient() {
        return redissonClient;
    }

    public void setRedissonClient(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public Long getCreatorId() {
        return creatorId;
    }

    public void setCreatorId(Long creatorId) {
        this.creatorId = creatorId;
    }

    public String getCreatorName() {
        return creatorName;
    }

    public void setCreatorName(String creatorName) {
        this.creatorName = creatorName;
    }

    public Long getModifierId() {
        return modifierId;
    }

    public void setModifierId(Long modifierId) {
        this.modifierId = modifierId;
    }

    public String getModifierName() {
        return modifierName;
    }

    public void setModifierName(String modifierName) {
        this.modifierName = modifierName;
    }

    public LocalDateTime getGmtCreate() {
        return gmtCreate;
    }

    public void setGmtCreate(LocalDateTime gmtCreate) {
        this.gmtCreate = gmtCreate;
    }

    public LocalDateTime getGmtModified() {
        return gmtModified;
    }

    public void setGmtModified(LocalDateTime gmtModified) {
        this.gmtModified = gmtModified;
    }

    public Long getShopId() {
        return shopId;
    }

    public void setShopId(Long shopId) {
        this.shopId = shopId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getObjectId() {
        return objectId;
    }

    public void setObjectId(String objectId) {
        this.objectId = objectId;
    }

    public String getActClass() {
        return actClass;
    }

    public Byte getStatus() {
        return status;
    }

    public void setActClass(String actClass) {
        this.actClass = actClass;
    }

    public LocalDateTime getCouponTime() {
        return couponTime;
    }

    public void setCouponTime(LocalDateTime couponTime) {
        this.couponTime = couponTime;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public Integer getQuantityType() {
        return quantityType;
    }

    public void setQuantityType(Integer quantityType) {
        this.quantityType = quantityType;
    }

    public Integer getValidTerm() {
        return validTerm;
    }

    public void setValidTerm(Integer validTerm) {
        this.validTerm = validTerm;
    }

    public void setStatus(Byte status) {
        this.status = status;
    }

    public void claimCoupon(Long customerId, UserDto user) {
        RLock redisLock = redissonClient.getLock("lock:couponAct:" + this.objectId);
        boolean isLock = redisLock.tryLock();
        if (!isLock) {
            throw new BusinessException(ReturnNo.COUPON_EXIST, String.format(ReturnNo.COUPON_EXIST.getMessage(), "优惠券已领取", this.id));
        }
        try {
            if (this.quantity < 1) {
                throw new BusinessException(ReturnNo.COUPON_FINISH, String.format(ReturnNo.COUPON_FINISH.getMessage(), "优惠券已领完", this.id));
            }
            if (this.couponTime.isAfter(LocalDateTime.now())) {
                throw new BusinessException(ReturnNo.COUPON_NOTBEGIN, String.format(ReturnNo.COUPON_NOTBEGIN.getMessage(), "优惠卷活动未到时间", this.couponTime));
            }

            if (this.couponTime.plusDays(this.validTerm).isBefore(LocalDateTime.now())) {
                throw new BusinessException(ReturnNo.COUPON_TIMELATE, String.format(ReturnNo.COUPON_TIMELATE.getMessage(), "优惠卷活动终止", this.validTerm));
            }

            this.couponDao.retrieveCouponByCustomerIdAndActId(customerId, this.id);
            Long count = this.couponDao.findById() + 1;

            Coupon coupon = Coupon.builder().couponSn("C00" + count).name(this.name).customerId(customerId).activityId(this.id).beginTime(this.couponTime).endTime(this.couponTime.plusDays(this.validTerm)).used(0).build();

            if (this.quantityType == 1) {
                this.setQuantity(this.quantity - 1);
                couponActDao.save(this, user);
            }

            couponDao.insert(coupon, user);
        } finally {
            // 释放锁
            redisLock.unlock();
        }


    }
}